#include <malloc.h>
#include "c_Engine.h"
#include "c_Texture.h"
/**
 * default constructor
 */
wiigi::c_Texture::c_Texture( void )
:
   m_Signature( d_Signature ),
   
   m_Width( 0 ),
   m_Height( 0 ),
   m_Data( 0 )
{
   memset( &m_GX_TexObj, 0, sizeof( m_GX_TexObj ) );
   
   return;
}

/**
 * destructor
 */
wiigi::c_Texture::~c_Texture( )
{
   
   
   return;
}

/**
 * creates texture from Buffer
 *
 * @param  Buffer   Memory buffer containing image file
 * @retval e_Status status of request
 */
wiigi::e_Status wiigi::c_Texture::createFromBuffer( const unsigned char Buffer[] )
{
   PNGUPROP imgProp;
   IMGCTX ctx;
   
   ctx = PNGU_SelectImageFromBuffer(Buffer);
   PNGU_GetImageProperties (ctx, &imgProp);
   m_Data = memalign (32, imgProp.imgWidth * imgProp.imgHeight * 4);
   PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, m_Data, 255);
   PNGU_ReleaseImageContext (ctx);
   m_Width = imgProp.imgWidth;
   m_Height = imgProp.imgHeight;
   
   flushData();
   
   GX_InitTexObj(&m_GX_TexObj, m_Data, m_Width, m_Height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
   GX_InitTexObjLOD(&m_GX_TexObj, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1);

   return d_StatusOK;
}

/**
 * returns a texture frame covering the whole texture
 */
void wiigi::c_Texture::getFullFrame( 
   s_2D_TextCoords& Frame
)
{
   Frame.s1 = 0;
   Frame.t1 = 0;
   Frame.s2 = 1;
   Frame.t2 = 1;
   
   return;
}

/**
 * Assumes that the texture is actually a collection of smaller frames.
 * returns a frame for the frame number / size specified
 *
 * based on code from spiffen
 */
void wiigi::c_Texture::getSubFrame( 
   s_2D_TextCoords& TextureFrame,
   u32              FrameNumber,
   c_u32Rect&       FrameSize
)
{
   const u32 FramesAccross = ( m_Width / FrameSize.getWidth() );    //Ignore frames that fall off of edge of texture
   const u32 FramesDown    = ( m_Height / FrameSize.getHeight() );
   
   if( FrameNumber >= ( FramesAccross * FramesDown ) )
   {
      //invalid frame number
      getFullFrame( TextureFrame );
      return;
   }
   
   f32 Xpos = (f32) ( ( FrameNumber % FramesAccross ) * FrameSize.getWidth() );
   f32 Ypos = (f32) ( ( FrameNumber / FramesAccross ) * FrameSize.getHeight() );
   
   const f32 S_CORRECTION = d_FRAME_CORR / (f32)m_Width;
   const f32 T_CORRECTION = d_FRAME_CORR / (f32)m_Height;
   
#if 0
   // Frame Correction by spiffen
    f32 FRAME_CORR = 0.001f;
    f32 s1 = (((frame%tex.nbtilew))/(f32)tex.nbtilew)+(FRAME_CORR/tex.w);
    f32 s2 = (((frame%tex.nbtilew)+1)/(f32)tex.nbtilew)-(FRAME_CORR/tex.w);
    f32 t1 = (((int)(frame/tex.nbtilew))/(f32)tex.nbtileh)+(FRAME_CORR/tex.h);
    f32 t2 = (((int)(frame/tex.nbtilew)+1)/(f32)tex.nbtileh)-(FRAME_CORR/tex.h);
#endif
   
   TextureFrame.s1 = ( Xpos / (f32)m_Width ) + S_CORRECTION;
   
   TextureFrame.s2 = ( ( Xpos + (f32)FrameSize.getWidth() ) / m_Width ) - S_CORRECTION;

   TextureFrame.t1 = ( Ypos / (f32)m_Height ) + T_CORRECTION;
   
   TextureFrame.t2 = ( ( Ypos + (f32)FrameSize.getHeight() ) / m_Height ) - T_CORRECTION;
   
   return;
}

/**
 * given a pixel position within texture, return frame that covers it.
 */
void wiigi::c_Texture::getSubFrame( 
   s_2D_TextCoords&     TextureFrame,
   c_u32Rect&           FrameSize
)
{
   const f32 S_CORRECTION = d_FRAME_CORR / (f32)m_Width;
   const f32 T_CORRECTION = d_FRAME_CORR / (f32)m_Height;
   
   TextureFrame.s1 = ( (f32)FrameSize.getLeft() / (f32)m_Width ) + S_CORRECTION;
   
   TextureFrame.s2 = ( (f32)FrameSize.getRight() / m_Width ) - S_CORRECTION;

   TextureFrame.t1 = ( (f32)FrameSize.getTop() / (f32)m_Height ) + T_CORRECTION;
   
   TextureFrame.t2 = ( (f32)FrameSize.getBottom() / m_Height ) - T_CORRECTION;

   return;   
}
